package com.baliejun.springsell.service.impl;

import com.baliejun.springsell.bean.OrderDetail;
import com.baliejun.springsell.bean.OrderMaster;
import com.baliejun.springsell.bean.ProductInfo;
import com.baliejun.springsell.converter.OrderMasterToOrderMasterDTOConverter;
import com.baliejun.springsell.dao.OrderDetailDao;
import com.baliejun.springsell.dao.OrderMasterDao;
import com.baliejun.springsell.dto.OrderCartDTO;
import com.baliejun.springsell.dto.OrderMasterDTO;
import com.baliejun.springsell.enums.OrderStatusEnum;
import com.baliejun.springsell.enums.PayStatusEnum;
import com.baliejun.springsell.enums.ResultEnum;
import com.baliejun.springsell.exception.SellException;
import com.baliejun.springsell.service.OrderMasterService;
import com.baliejun.springsell.service.ProductInfoService;
import com.baliejun.springsell.util.KeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Author: LiejunBa
 * @Description:订单service
 * @Date: 2020/12/2 4:28 下午
 */
@Slf4j
@Service
public class OrderMasterImpl implements OrderMasterService {

    @Autowired
    private ProductInfoService productInfoService;

    @Autowired
    private OrderDetailDao orderDetailDao;

    @Autowired
    private OrderMasterDao orderMasterDao;


    //订单主表的创建
    @Override
    @Transactional
    public OrderMasterDTO create(OrderMasterDTO orderMasterDTO) {

        //订单主表生成的时候，就会创建订单id

        String orderId = KeyUtil.genUniqueKey();

        //总价,初始化是0
        BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);

        //1.查询商品,循环遍历订单详情
        for (OrderDetail orderDetail : orderMasterDTO.getOrderDetailList()){
            ProductInfo productInfo = productInfoService.findOne(orderDetail.getProductId());
            if (productInfo == null){
                throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
            }
            //2.计算订单总价
            orderAmount = productInfo.getProductPrice().
                    multiply(new BigDecimal(orderDetail.getProductQuantity())).add(orderAmount);

            //订单详情入库
            orderDetail.setDetailId(KeyUtil.genUniqueKey());//订单详情ID
            orderDetail.setOrderId(orderId);
            BeanUtils.copyProperties(productInfo, orderDetail);
            orderDetailDao.save(orderDetail);

        }

        //3.写入订单数据库（orderMaster和orderDetail）
        OrderMaster orderMaster = new OrderMaster();
        orderMasterDTO.setOrderId(orderId);
        BeanUtils.copyProperties(orderMasterDTO, orderMaster);
        orderMaster.setOrderAmount(orderAmount);
        orderMaster.setOrderStatus(OrderStatusEnum.New.getCode());
        orderMaster.setPayStatus(PayStatusEnum.WATI.getCode());
        orderMasterDao.save(orderMaster);

        //4.扣库存
        //lamalar表达式
        List<OrderCartDTO> orderCartDTOList = orderMasterDTO.getOrderDetailList().stream().
                map(e -> new OrderCartDTO(e.getProductId(),e.getProductQuantity()) ).collect(Collectors.toList());

        productInfoService.decreaseStock(orderCartDTOList);

        return orderMasterDTO;
    }

    @Override
    public OrderMasterDTO findOne(String orderId) {

        Optional<OrderMaster> optional = orderMasterDao.findById(orderId);
        OrderMaster orderMaster = optional.get();
        if (orderMaster == null){
            throw new SellException(ResultEnum.ORDER_NOT_EXIST);
        }
        List<OrderDetail> orderDetailList = orderDetailDao.findByOrderId(orderId);
        if (CollectionUtils.isEmpty(orderDetailList)){
            throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
        }

        OrderMasterDTO orderMasterDTO = new OrderMasterDTO();
        BeanUtils.copyProperties(orderMaster, orderMasterDTO);
        orderMasterDTO.setOrderDetailList(orderDetailList);

        return orderMasterDTO ;
    }

    //查询某个买家的订单
    @Override
    public Page<OrderMasterDTO> findList(String buyerOpenid, Pageable pageable) {

        Page<OrderMaster> page = orderMasterDao.findByBuyerOpenid(buyerOpenid, pageable);
        List<OrderMaster> orderMasterList = page.getContent();

        List<OrderMasterDTO> orderMasterDTOList = OrderMasterToOrderMasterDTOConverter.convert(orderMasterList);

        //需要将orderMasterList转换成orderMasterDTOList

        Page<OrderMasterDTO> orderMasterDTOPage = new PageImpl<OrderMasterDTO>(orderMasterDTOList,pageable,page.getTotalElements());

        return orderMasterDTOPage;
    }

    @Override
    @Transactional
    public OrderMasterDTO cancel(OrderMasterDTO orderMasterDTO) {

        OrderMaster orderMaster = new OrderMaster();

        //判断订单状态
        if (!orderMasterDTO.getOrderStatus().equals(OrderStatusEnum.New.getCode())){
            //新下单
            log.error("[取消订单]订单状态不正确，orderId={},orderStatus={}",orderMasterDTO.getOrderId(),orderMasterDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }

        //修改订单状态
        orderMasterDTO.setOrderStatus(OrderStatusEnum.CANCLE.getCode());
        BeanUtils.copyProperties(orderMasterDTO, orderMaster);
        OrderMaster updateResult = orderMasterDao.save(orderMaster);

        if (updateResult == null){
            log.error("[取消订单]更新失败，orderMaster={}",orderMaster);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }

        //取消之后返回库存

        if (CollectionUtils.isEmpty(orderMasterDTO.getOrderDetailList())){
            throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
        }

        List<OrderCartDTO> orderCartDTOList = orderMasterDTO.getOrderDetailList().stream().map(e -> new OrderCartDTO(e.getProductId(), e.getProductQuantity())).collect(Collectors.toList());

        productInfoService.increaseStock(orderCartDTOList);


        //如果已经支付，需要退款
        if (orderMasterDTO.getPayStatus().equals(PayStatusEnum.SUCCESS)){
            //TODO
        }

        return orderMasterDTO;
    }

    @Override
    @Transactional
    public OrderMasterDTO finish(OrderMasterDTO orderMasterDTO) {

        //判断订单状态，如果订单状态不等于新下单，就会报错
        if (!orderMasterDTO.getOrderStatus().equals(OrderStatusEnum.New.getCode())){
            log.error("[完结订单]订单状态不正确");
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //修改订单状态
        orderMasterDTO.setOrderStatus(OrderStatusEnum.FINISHED.getCode());
        OrderMaster orderMaster = new OrderMaster();
        BeanUtils.copyProperties(orderMasterDTO, orderMaster);
        OrderMaster updateResult = orderMasterDao.save(orderMaster);
        if (updateResult == null){
            log.error("[完结订单]更新失败，orderMaster={}",orderMaster);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }

        return orderMasterDTO;
    }

    @Override
    @Transactional
    public OrderMasterDTO paid(OrderMasterDTO orderMasterDTO) {
        //判断订单状态，新订单
        if(!orderMasterDTO.getOrderStatus().equals(OrderStatusEnum.New.getCode())){
            log.error("[完结订单]订单状态不正确");
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //判断支付状态
        if (!orderMasterDTO.getPayStatus().equals(PayStatusEnum.WATI.getCode())){
            log.error("[订单支付]订单支付状态不正确");
            throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR);
        }
        OrderMaster orderMaster = new OrderMaster();
        //修改的支付状态
        orderMasterDTO.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        BeanUtils.copyProperties(orderMasterDTO, orderMaster);
        OrderMaster updateResult = orderMasterDao.save(orderMaster);
        if (updateResult == null){
            log.error("[订单支付]更新失败，orderMaster={}",orderMaster);
            throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
        }

        return orderMasterDTO;
    }
}
